package net.wicp.tams.common.thread.threadlocal;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import net.wicp.tams.common.apiext.CollectionUtil;

/****
 * 每个线程的实例封装
 * 
 * @author zhoujunhui
 *
 */
@SuppressWarnings("all")
public class PerthreadManager {
	private static PerthreadManager INSTANCE = new PerthreadManager();

	private PerthreadManager() {
	}

	public static final PerthreadManager getInstance() {
		return INSTANCE;
	}

	public static class MapHolder extends ThreadLocal<Map> {
		@Override
		protected Map initialValue() {
			return CollectionUtil.newMap();
		}
	}

	private final class DefaultPerThreadValue<T> implements PerThreadValue<T> {
		private final Object key;

		DefaultPerThreadValue(final Object key) {
			this.key = key;

		}

		@Override
		public T get() {
			return get(null);
		}

		@Override
		public T get(T defaultValue) {
			Map map = getPerthreadMap();

			Object storedValue = map.get(key);

			if (storedValue == null) {
				return defaultValue;
			}

			if (storedValue == NULL_VALUE) {
				return null;
			}

			return (T) storedValue;
		}

		@Override
		public T set(T newValue) {
			getPerthreadMap().put(key, newValue == null ? NULL_VALUE : newValue);

			return newValue;
		}

		@Override
		public boolean exists() {
			return getPerthreadMap().containsKey(key);
		}
	}

	private final class DefaultObjectCreator<T> implements ObjectCreator<T> {

		private final Object key;
		private final ObjectCreator<T> delegate;

		DefaultObjectCreator(final Object key, final ObjectCreator<T> delegate) {
			this.key = key;
			this.delegate = delegate;
		}

		public T createObject() {
			Map map = getPerthreadMap();
			T storedValue = (T) map.get(key);

			if (storedValue != null) {
				return (storedValue == NULL_VALUE) ? null : storedValue;
			}

			T newValue = delegate.createObject();

			map.put(key, newValue == null ? NULL_VALUE : newValue);

			return newValue;
		}
	}

	private final MapHolder holder = new MapHolder();
	private static Object NULL_VALUE = new Object();
	// private final AtomicInteger uuidGenerator = new AtomicInteger();

	private Map getPerthreadMap() {
		return holder.get();
	}

	/***
	 * 每个线程，第一次用delegate创建一个实例，后面将重用这个实例
	 * 
	 * @param key
	 *            实例所在key
	 * @param delegate
	 *            代理
	 * 
	 * @param <T>
	 *            要返回实例的类型
	 * @return 实例
	 */
	public <T> ObjectCreator<T> createValue(final Object key, final ObjectCreator<T> delegate) {
		return new DefaultObjectCreator<T>(key, delegate);
	}

	/***
	 * 清除本线程的数据
	 * 
	 * @param key
	 *            实例所在key
	 */
	public void cleanValue(final Object key) {
		Map map = getPerthreadMap();
		map.remove(key);
	}

	public <T> PerThreadValue<T> createValue(final Object key) {
		return new DefaultPerThreadValue(key);
	}

}
